import React = require("react");

export type Status = "loading" | "complete" | "fail";

export interface SpinerState {
    status?: Status
}

export abstract class SpinerComponent<P, S extends SpinerState = {}> extends React.Component<P, S> {
    abstract loadData(): Promise<Partial<S>>;

    constructor(props: P) {
        super(props);

        let render = this.render;
        console.assert(render != null);
        this.render = () => {
            let { status } = this.state || {} as SpinerState;
            status = status || "loading";
            if (status == "loading") {
                return <div className="loading">数据正在加载中...</div>
            }
            else if (status == "fail") {
                return <div className="empty" onClick={() => this._loadData()}>
                    <div className="empty">页面加载失败,点击重新加载</div>
                </div>
            }

            return render.apply(this);
        }

        let componentDidMount = this.componentDidMount;
        this.componentDidMount = async () => {
            this._loadData();
            if (componentDidMount)
                componentDidMount.apply(this);
        }
    }

    componentWillReceiveProps() {
        this._loadData();
    }

    private async _loadData() {

        this.setState({ status: "loading" });

        try {
            let s = await this.loadData() as S;
            if (s == null) {
                this.setState({ status: "fail" })
            }
            else {
                s.status = "complete";
                this.setState(s);
            }
        }
        catch (err) {
            this.setState({ status: "fail" });
            console.error(err)
        }
    }

}